//// This file is part of the uSTL library, an STL implementation.
////
//// Copyright (c) 2005-2009 by Mike Sharov <msharov@users.sourceforge.net>
//// This file is free software, distributed under the MIT License.
////
///// \file uctrstrm.h
/////
///// \brief Serialization templates for standard containers.
///// Because containers are templates, a single operator>> is impossible.
///// Making virtual read/write is also impossible because not all containers
///// contain serializable elements. Therefore, use the macros in this file.
//
//#ifndef UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
//#define UCTRSTRM_H_75B2C3EA4980DDDC6B6DFFF767A3B7AC
//
//#include "mistream.h"
//#include "sostream.h"
//#include "uiosfunc.h"
//#include <typeinfo>
//
//namespace ustl {
//
////----------------------------------------------------------------------
//// Macros for easily declaring a container streamable.
////----------------------------------------------------------------------
//
///// \brief Declares container template \p type streamable.
/////
///// Use TEMPLATE_TYPE and TEMPLATE_DECL macros to pass in templated
///// type with commas and the template declaration.
/////
//#define STD_TEMPLATE_CTR_STREAMABLE(type, template_decl)	\
//    template_decl						\
//    inline istream& operator>> (istream& is, type& v)		\
//    { return (container_read (is, v)); } 			\
//    template_decl						\
//    inline ostream& operator<< (ostream& os, const type& v)	\
//    { return (container_write (os, v)); } 			\
//    template_decl						\
//    inline ostringstream& operator<< (ostringstream& os, const type& v)	\
//    { return (container_text_write (os, v)); }			\
//    template_decl						\
//    struct object_stream_size<type > {				\
//	inline size_t operator()(const type& v)	const		\
//	    { return (container_stream_size (v)); }		\
//    };
//
///// \brief Declares non-resizable container template \p type streamable.
//#define STD_TEMPLATE_NR_CTR_STREAMABLE(type, template_decl)	\
//    template_decl						\
//    inline istream& operator>> (istream& is, type& v)		\
//    { return (nr_container_read (is, v)); } 			\
//    template_decl						\
//    inline ostream& operator<< (ostream& os, const type& v)	\
//    { return (nr_container_write (os, v)); } 			\
//    template_decl						\
//    inline ostringstream& operator<< (ostringstream& os, const type& v)	\
//    { return (container_text_write (os, v)); }			\
//    template_decl						\
//    struct object_stream_size<type > {				\
//	inline size_t operator()(const type& v)	const		\
//	    { return (nr_container_stream_size (v)); }		\
//    };
//
////----------------------------------------------------------------------
//// Fixed size container serialization.
////----------------------------------------------------------------------
//
///// Reads fixed size container \p v from stream \p is.
//template <typename Container>
//inline istream& nr_container_read (istream& is, Container& v)
//{
//    foreach (typename Container::iterator, i, v)
//	is >> *i;
//    return (is);
//}
//
///// Writes fixed size container \p v into stream \p os.
//template <typename Container>
//inline ostream& nr_container_write (ostream& os, const Container& v)
//{
//    foreach (typename Container::const_iterator, i, v)
//	os << *i;
//    return (os);
//}
//
///// Computes the stream size of a fixed size standard container.
//template <typename Container>
//inline size_t nr_container_stream_size (const Container& v)
//{
//    typedef typename Container::const_iterator vciter_t;
//    typedef typename iterator_traits<vciter_t>::value_type value_type;
//    if (!v.size())
//	return (0);
//    size_t s = 0, dvs;
//    vciter_t i = v.begin();
//    do {
//	dvs = stream_size_of(*i);
//	s += dvs;
//    } while (++i != v.end() && !__builtin_constant_p(dvs));
//    if (__builtin_constant_p(dvs))
//	s *= v.size();
//    return (s);
//}
//
////----------------------------------------------------------------------
//// Resizable container serialization.
////----------------------------------------------------------------------
//
///// Reads container \p v from stream \p is.
//template <typename Container>
//istream& container_read (istream& is, Container& v)
//{
//    typedef typename Container::value_type value_type;
//    typedef typename Container::iterator iterator;
//    typedef typename Container::written_size_type written_size_type;
//    written_size_type n = 0;
//    is >> n;
//    const size_t expectedSize = n * stream_size_of(value_type());
//    if (!is.verify_remaining ("read", typeid(v).name(), expectedSize))
//	return (is);
//    if (alignof(NullValue<value_type>()) > alignof(n))
//	is >> ios::talign<value_type>();
//    v.resize (n);
//    nr_container_read (is, v);
//    is >> ios::talign<written_size_type>();
//    return (is);
//}
//
///// Writes the vector to stream \p os.
//template <typename Container>
//ostream& container_write (ostream& os, const Container& v)
//{
//    typedef typename Container::value_type value_type;
//    typedef typename Container::written_size_type written_size_type;
//    const written_size_type sz (v.size());
//    os << sz;
//    if (alignof(NullValue<value_type>()) > alignof(sz))
//	os << ios::talign<value_type>();
//    nr_container_write (os, v);
//    os << ios::talign<written_size_type>();
//    return (os);
//}
//
///// Computes the stream size of a standard container.
//template <typename Container>
//size_t container_stream_size (const Container& v)
//{
//    typedef typename Container::value_type value_type;
//    typedef typename Container::written_size_type written_size_type;
//    const written_size_type sz (v.size());
//    size_t sizeSize = stream_size_of (sz);
//    if (alignof(NullValue<value_type>()) > alignof(sz))
//	sizeSize = Align (sizeSize, alignof(NullValue<value_type>()));
//    return (Align (sizeSize + nr_container_stream_size (v), alignof(sz)));
//}
//
///// \brief Writes element \p v into stream \p os as text.
///// Specialize to custom print elements.
//template <typename T>
//inline ostringstream& container_element_text_write (ostringstream& os, const T& v)
//{ return (os << v); }
//
///// Writes container \p v into stream \p os as text.
//template <typename Container>
//ostringstream& container_text_write (ostringstream& os, const Container& v)
//{
//    typename Container::const_iterator i = v.begin();
//    os << '(';
//    while (i < v.end()) {
//	container_element_text_write (os, *i);
//	os << ",)"[++i == v.end()];
//    }
//    return (os);
//}
//
////----------------------------------------------------------------------
//
//} // namespace ustl
//
//#endif
